﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using System.Web;
using Microsoft.SharePoint.Taxonomy;

namespace SharePointHelper.DLL.SSOM
{
	public class Field
	{

		/// <summary>
		/// Determine if field exists for list item
		/// Does not log an error if field does not exist
		/// IMPORTANT! If field exists but was not fetched from custom query, will still return true!
		/// To test if field exists AND was fetched (part of CAML query ViewFields), use the IsExistAndFetched() member
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname">display name or internal name</param>
		/// <returns></returns>
		public static bool IsExist(SPListItem item, string fieldname)
		{
			bool isExist = false;
			try
			{
				// init
				isExist = (item != null) ? item.Fields.ContainsField(fieldname) : false;
			}
			catch (Exception ex)
			{
				// Log.WriteError("e5yhe6uerrewyrdrs", ex, "fieldname: " + fieldname);
			}
			return isExist;
		}
		/// <summary>
		/// determine if field exists for list passed
		/// </summary>
		/// <param name="list"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static bool IsExist(SPList list, string fieldname)
		{
			return (list != null) ? list.Fields.ContainsField(fieldname) : false;
		}


		/// <summary>
		/// Determined if SPListItem has the passed field fetched. This is useful when only fetching limited
		/// fields using SPQuery ViewFields and want to make sure field was fetched
		/// Does not log an error if field not found
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static bool IsFetched(SPListItem item, string fieldname)
		{
			bool isFetched = false;
			if (item != null && !string.IsNullOrEmpty(fieldname))
			{
				if (item.ListItems != null)
				{
					// loop through parent item collection to see if field was fetched
					foreach (SPField f in item.ListItems.Fields)
					{
						if (f.InternalName == fieldname)
						{
							isFetched = true;
							break;
						}
					}
				}
				else
				{
					// try to access the field, if throw error, then know it wasn't fetched
					try { var fieldValue = item[fieldname]; if (fieldValue != null) { isFetched = true; } }
					catch { isFetched = false; }
				}
			}
			return isFetched;
		}

		/// <summary>
		/// Determine if field exists AND it was fetched with a value
		/// If only need to see if a field exists, use IsExist(). 
		/// This is useful to determine if field exists and data was fetched from SPQuery
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static bool IsExistAndFetched(SPListItem item, string fieldname)
		{
			if (IsExist(item, fieldname) && IsFetched(item, fieldname)) { return true; }
			else { return false; }
		}

		/// <summary>
		/// Convert a field display name to internal name
		/// </summary>
		/// <param name="displayName"></param>
		/// <returns></returns>
		public static string ConvertDisplayNameToInternalName(string displayName)
		{
			string internalName = string.Empty;
			try
			{
				// init
				if (string.IsNullOrEmpty(displayName)) { throw new Exception("Display name passed is null"); }
				if (displayName.Length > 200) { throw new Exception("Display name greater than 200 char, max length is 255"); }

				// dictionary of escaped chars
				Dictionary<char, string> escapedChars = new Dictionary<char, string>();
				escapedChars.Add(' ', "_X0020_");
				escapedChars.Add('|', "_X007C_");
				escapedChars.Add('-', "_X002D_");
				escapedChars.Add('"', "_X005C_");
				escapedChars.Add('(', "_X0028_");
				escapedChars.Add(')', "_X0029_");
				escapedChars.Add('\'', "_X0027_");
				escapedChars.Add(',', "_X002C_");
				escapedChars.Add('!', "_X0021_");
				escapedChars.Add('%', "_X0025_");
				escapedChars.Add('&', "_X0026_");
				escapedChars.Add('?', "_X003F_");
				escapedChars.Add('$', "_X0024_");
				escapedChars.Add('£', "_X00A3_");
				escapedChars.Add('"', "_X0022_");
				escapedChars.Add('<', "_X003C_");
				escapedChars.Add('>', "_X003E_");
				escapedChars.Add('=', "_X003D_");
				escapedChars.Add('#', "_X0023_");

				for (int i = 0; i < displayName.Length; i++)
				{
					bool isMatch = false;
					foreach (KeyValuePair<char, string> escapedChar in escapedChars)
					{
						if (displayName[i] == escapedChar.Key)
						{
							// found illegal char, replace
							isMatch = true;
							internalName += escapedChar.Value;
							break;
						}
					}
					if (!isMatch)
					{
						// legal char, add
						internalName += displayName[i];
					}
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("5eesrhserg45tr", ex, "displayName: " + displayName);
				internalName = null;
			}
			return internalName;
		}

		/// <summary>
		/// set users/groups field
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <param name="usersToAdd"></param>
		/// <param name="isAppend"></param>
		/// <returns></returns>
		public static bool SetUsersInPeoplePicker(SPListItem item, string fieldname, SPFieldUserValueCollection usersToAdd, 
			bool isAppend)
		{
			bool isSuccess = true;
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (!Field.IsExist(item, fieldname)) { throw new Exception("Field: " + fieldname + " does not exist for passed item"); }
				if (isAppend && usersToAdd == null || usersToAdd.Count == 0)
				{
					throw new Exception("Cannot append an empty collection of users");
				}

				if (usersToAdd != null)
				{
					if (isAppend)
					{
						// get all current users
						var currentUsers = GetUsersFromPeoplePicker(item, fieldname);
						if (currentUsers != null && currentUsers.Count > 0)
						{
							// merge
							foreach (SPUser currentUser in currentUsers)
							{
								bool isMatch = false;
								foreach (SPFieldUserValue userToAdd in usersToAdd)
								{
									if (currentUser.ID == userToAdd.LookupId)
									{
										isMatch = true;
										break;
									}
								}
								if (!isMatch)
								{
									// existing user not found in list of users to add, add it
									usersToAdd.Add(new SPFieldUserValue(item.Web, currentUser.ID, currentUser.Name));
								}
							}
						} // foreach current user
					}
					
					// add users
					if (usersToAdd.Count == 0)
					{
						// remove all users
						item[fieldname] = null;
					}
					else
					{
						item[fieldname] = usersToAdd;
					}
				}

			}
			catch (Exception ex)
			{
				string title = (item != null) ? item.Title : null;
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("5e6thrsaegwsreser", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title);
				isSuccess = false;
			}
			return isSuccess;
		}

		/// <summary>
		/// Add a user to people picker field
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <param name="userToAdd"></param>
		/// <param name="isAppend"></param>
		/// <returns></returns>
		public static bool SetUsersInPeoplePicker(SPListItem item, string fieldname, SPUser userToAdd,
			bool isAppend)
		{
			var usersToAdd = new List<SPUser>(); if (userToAdd != null) { usersToAdd.Add(userToAdd); }
			return SetUsersInPeoplePicker(item, fieldname, usersToAdd, isAppend);
		}

		/// <summary>
		/// set users/groups field
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <param name="usersToAdd"></param>
		/// <param name="isAppend"></param>
		/// <returns></returns>
		public static bool SetUsersInPeoplePicker(SPListItem item, string fieldname, List<SPUser> usersToAdd,
			bool isAppend)
		{
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }

				// convert collection
				SPFieldUserValueCollection usersConverted = null;
				if (usersToAdd != null)
				{
					usersConverted = new SPFieldUserValueCollection();
					foreach (SPUser user in usersToAdd)
					{
						usersConverted.Add(new SPFieldUserValue(item.Web, user.ID, user.Name));
					}
				}

				// call original
				return SetUsersInPeoplePicker(item, fieldname, usersConverted, isAppend);
			}
			catch (Exception ex)
			{
				Log.WriteError("54i7r6t6jhseagwsfsdzf", ex);
				return false;
			}
		}

		public static bool SetUsersInPeoplePicker(SPListItem item, string fieldname, List<string> usernames,
			bool isCreateUserIfDoesntExist, bool isAppend)
		{
			bool isSuccess = true;
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				var users = new List<SPUser>();

				// create SPUsers collection
				foreach (string username in usernames)
				{
					var user = Security.GetUser(username, isCreateUserIfDoesntExist, item.Web);
					if (isCreateUserIfDoesntExist && user == null)
					{
						throw new Exception("Failed to create user " + username + " to be added to people picker: " + fieldname);
					}
					else if (user != null)
					{
						users.Add(user);
					}
				}

				// call original
				isSuccess = SetUsersInPeoplePicker(item, fieldname, users, isAppend);
			}
			catch (Exception ex)
			{
				string title = (item != null) ? item.Title : null;
				string usernameAsString = (usernames != null) ? Utilities.ConvertListToString(usernames) : null;
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("568eutydhtfdsszder", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title + ", usernames passed: " + usernameAsString);
				isSuccess = false;
			}
			return isSuccess;
		}



		/// <summary>
		/// Get SP users from people picker
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <param name="errorUsers"></param>
		/// <returns></returns>
		public static List<SPUser> GetUsersFromPeoplePicker(SPListItem item, string fieldname)
		{
			List<SPUser> users = null;
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (!Field.IsExist(item, fieldname)) { throw new Exception("Field: " + fieldname + " does not exist for passed item"); }
				users = new List<SPUser>();


				SPFieldUserValueCollection usersCollection = null;
				string selectedUsers = Field.GetStringValue(item, fieldname);

				if (!string.IsNullOrEmpty(selectedUsers))
				{
					usersCollection = new SPFieldUserValueCollection(item.Web, selectedUsers);
					if (usersCollection != null)
					{
						foreach (SPFieldUserValue uv in usersCollection)
						{
							users.Add(uv.User);
						}
					}
				}
			}
			catch (Exception ex)
			{
				string title = null; if (item != null) { title = item.Title; }
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("5tjhffdhdrsrtrt", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title);
				users = null;
			}
			return users;
		}

		

		/// <summary>
		/// Get int value from field
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static int? GetIntValue(SPListItem item, string fieldname)
		{
			int? v = null;
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (!IsExist(item, fieldname)) { throw new Exception("Field: " + fieldname + " does not exist for passed item"); }

				// get string value and cast
				if (item[fieldname] != null) { v = Convert.ToInt32(item[fieldname]); }
			}
			catch (Exception ex)
			{
				string title = null; if (item != null) { title = item.Title; }
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("rdttdfdrdrer", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title);
				v = null;
			}
			return v;
		}

		/// <summary>
		/// Get double value from field
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static double? GetDoubleValue(SPListItem item, string fieldname)
		{
			double? v = null;
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (!IsExist(item, fieldname)) { throw new Exception("Field: " + fieldname + " does not exist for passed item"); }

				// get string value and cast
				if (item[fieldname] != null) { v = Convert.ToDouble(item[fieldname]); }
			}
			catch (Exception ex)
			{
				string title = null; if (item != null) { title = item.Title; }
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("fthutdseryyes55ey", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title);
				v = null;
			}
			return v;
		}

		/// <summary>
		/// Get dateTime value from field
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static DateTime? GetDateTimeValue(SPListItem item, string fieldname)
		{
			DateTime? v = null;
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (!IsExist(item, fieldname)) { throw new Exception("Field: " + fieldname + " does not exist for passed item"); }

				// get string value and cast
				if (item[fieldname] != null) { v = Convert.ToDateTime(item[fieldname]); }
			}
			catch (Exception ex)
			{
				string title = null; if (item != null) { title = item.Title; }
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("56urrsedrssee4", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title);
				v = null;
			}
			return v;
		}

		/// <summary>
		/// Get string value
		/// (doesn't html encode the value like GetHtmlValue() will)
		/// http://msdn.microsoft.com/en-us/library/ff521580.aspx
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static string GetStringValue(SPListItem item, string fieldname)
		{
			string o = null;
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (!IsExist(item, fieldname)) { throw new Exception("Field: " + fieldname + " does not exist for passed item"); }

				// get string
				var test = item[fieldname];
				if (test != null) { o = test.ToString(); }
			}
			catch (Exception ex)
			{
				string title = null; if (item != null) { title = item.Title; }
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("8iGt6t87oeresrer", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title);
				o = null;
			}
			return o;
		}

		/// <summary>
		/// Get string value from field
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static string GetTextValue(SPListItem item, string fieldname)
		{
			// call original
			try { return GetStringValue(item, fieldname); }
			catch { return null; }
		}

		/// <summary>
		/// Gets html from passed field
		/// results returned are html encoded
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <param name="isEditMode">If true, returns the WYSIWYG editor with the html value</param>
		/// <returns></returns>
		public static string GetHtmlValue(SPListItem item, string fieldname, bool isEditMode)
		{
			string o = null;
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (!IsExist(item, fieldname)) { throw new Exception("Field: " + fieldname + " does not exist for passed item"); }


				// get html
				if (item[fieldname] != null)
				{
					SPField f = GetField(item, fieldname);
					if (!isEditMode)
					{
						// get html
						o = f.GetFieldValueAsHtml(item[fieldname]);
					}
					else
					{
						// get html to edit
						o = f.GetFieldValueForEdit(item[fieldname]);
					}
				}
			}
			catch (Exception ex)
			{
				string title = null; if (item != null) { title = item.Title; }
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("fdusrdytrdrxff", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title);
				o = null;
			}
			return o;
		}

		/// <summary>
		/// Gets HTML, encoded for public view (not edit mode)
		/// OVERLOAD
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static string GetHtmlValue(SPListItem item, string fieldname)
		{
			// call original
			return GetHtmlValue(item, fieldname, false);
		}

		/// <summary>
		/// Get SharePoint Image Object from Field
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static Microsoft.SharePoint.Publishing.Fields.ImageFieldValue GetImageValue(SPListItem item, string fieldname)
		{
			Microsoft.SharePoint.Publishing.Fields.ImageFieldValue v = null;
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (!IsExist(item, fieldname)) { throw new Exception("Field: " + fieldname + " does not exist for passed item"); }


				if (item[fieldname] != null)
				{
					v = item[fieldname] as Microsoft.SharePoint.Publishing.Fields.ImageFieldValue;
				}
			}
			catch (Exception ex)
			{
				string title = null; if (item != null) { title = item.Title; }
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("9pyutgtddrser4t", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title);
				v = null;
			}
			return v;
		}

		/// <summary>
		/// get image url
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static string GetImageUrlValue(SPListItem item, string fieldname)
		{
			string url = null;
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (!IsExist(item, fieldname)) { throw new Exception("Field: " + fieldname + " does not exist for passed item"); }


				// 1.) get image
				Microsoft.SharePoint.Publishing.Fields.ImageFieldValue image = GetImageValue(item, fieldname);
				if (image != null)
				{
					url = image.ImageUrl;
				}
			}
			catch (Exception ex)
			{
				string title = null; if (item != null) { title = item.Title; }
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("32456rrddfs4ds", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title);
				url = null;
			}
			return url;
		}

		/// <summary>
		/// Get double value from field
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static bool? GetBoolValue(SPListItem item, string fieldname)
		{
			bool? v = null;
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (!IsExist(item, fieldname)) { throw new Exception("Field: " + fieldname + " does not exist for passed item"); }

				// get string value and cast
				if (item[fieldname] != null) 
				{
					// get boolean value based on "yes" or "no" value
					string fieldValueTest = Convert.ToString(item[fieldname]);
					if (!string.IsNullOrEmpty(fieldValueTest))
					{
						if (fieldValueTest.ToLower() == "yes") { return true; }
						else if (fieldValueTest.ToLower() == "no") { return false; }
					}
					v = Convert.ToBoolean(item[fieldname]); 
				}
			}
			catch (Exception ex)
			{
				string title = null; if (item != null) { title = item.Title; }
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("xsdfhyrtryr6rd", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title);
				v = null;
			}
			return v;
		}

		/// <summary>
		/// Get a specific field from passed list item
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname">Either internal name, or display name</param>
		/// <returns></returns>
		public static SPField GetField(SPListItem item, string fieldname)
		{
			SPField field = null;
			try
			{
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (string.IsNullOrEmpty(fieldname)) { throw new Exception("Fieldname passed is null"); }

				field = item.Fields.GetField(fieldname);
				if (field == null) { throw new Exception("Failed to get field: " + fieldname); }
			}
			catch (Exception ex)
			{
				string title = null; if (item != null) { title = item.Title; }
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("8yo09tr8767e5tdrdx", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title);
				field = null;
			}
			return field;
		}

		/// <summary>
		/// Get SPFieldUserValue from a field
		/// Field should only allow one user
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static SPFieldUserValue GetUserValue(SPListItem item, string fieldname)
		{
			SPFieldUserValue userValue = null;
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (!IsExist(item, fieldname)) { throw new Exception("Field: " + fieldname + " does not exist for passed item"); }


				// get user in unformatted text
				var fieldValue = Field.GetStringValue(item, fieldname);
				if (!string.IsNullOrEmpty(fieldValue)) { userValue = new SPFieldUserValue(item.Web, fieldValue); }
			}
			catch (Exception ex)
			{
				string title = null; if (item != null) { title = item.Title; }
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("ey5dgrdgre4dr", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title);
				userValue = null;
			}
			return userValue;
		}

		/// <summary>
		/// Get one SPUser from field
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static SPUser GetUser(SPListItem item, string fieldname)
		{
			try
			{
				var userValue = GetUserValue(item, fieldname);
				return (userValue != null) ? userValue.User : null;
			}
			catch
			{
				return null;
			}
		}

		public static SPFieldUserValueCollection GetUserValueCollection(SPListItem item, string fieldname)
		{
			SPFieldUserValueCollection userValueCollection = null;
			try 
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (!IsExist(item, fieldname)) { throw new Exception("Field: " + fieldname + " does not exist for passed item"); }

				userValueCollection = (SPFieldUserValueCollection)item[fieldname];
			}
			catch (Exception ex)
			{
				string title = null; if (item != null) { title = item.Title; }
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("u9y8ytyrtdrer4e4", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title);
				userValueCollection = null;
			}
			return userValueCollection;
		}

		/// <summary>
		/// Get collection of SPUsers for passed field
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static List<SPUser> GetUsers(SPListItem item, string fieldname)
		{
			List<SPUser> users = new List<SPUser>();
			var userValueCollection = GetUserValueCollection(item, fieldname);
			if (userValueCollection == null) { users = null; }
			else
			{
				foreach (var userValue in userValueCollection)
				{
					users.Add(userValue.User);
				}
			}
			return users;
		}

		/// <summary>
		/// Assign terms to a managed metadata column
		/// http://social.technet.microsoft.com/Forums/en/sharepoint2010programming/thread/9b8cb71c-ff56-4bb0-aaa7-ab4d16d99a8a
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static bool SetManagedMetadataField(SPListItem item, string fieldname, ICollection<Term> terms, bool isAppendExistingValue)
		{
			bool isSuccess = false;
			try
			{
				// init
				if (item == null) { throw new Exception("SPItem passed is null"); }
				if (string.IsNullOrEmpty(fieldname)) { throw new Exception("Fieldname passed is null"); }
				if (terms == null || terms.Count == 0) { throw new Exception("Invalid terms collection passed"); }


				// get field from item
				SPField field = null; field = GetField(item, fieldname);
				if (field == null) { throw new Exception("Failed to get field for item using fieldname: " + fieldname); }

				// make sure not assigning multiple terms
				if (!((TaxonomyField)field).AllowMultipleValues)
				{
					if (terms.Count > 1)
					{
						throw new Exception("Cannot assign more than one term to managed metadata field that only allows one term");
					}
					else if (isAppendExistingValue)
					{
						throw new Exception("Cannot append a term to a managed metadata field that only allows one term");
					}
				}

				// get SPsite
				SPSite site = item.ParentList.ParentWeb.Site;
				if (site == null) { throw new Exception("Failed to get SPSite for item passed"); }

				// append?
				if (isAppendExistingValue)
				{
					// get term store
					TermStore store = Taxonomy.GetTermStore(site);
					if (store == null) { throw new Exception("Failed to get termStore"); }

					// get current terms
					var existingTerms = Taxonomy.ConvertTaxonomyFieldValuesToTermCollection(
						GetManagedMetadataValue(item, fieldname), store);
					if (existingTerms != null && existingTerms.Count > 0)
					{
						// append terms
						foreach (Term t in existingTerms)
						{
							if (!terms.Contains(t)) { terms.Add(t); }
						}
					}
				}

				// set property
				if (terms.Count > 1)
				{
					((TaxonomyField)field).SetFieldValue(item, terms, 1033);
				}
				else if (terms.Count == 1)
				{
					Term term = null;
					foreach (Term t in terms) { term = t; break; }
					((TaxonomyField)field).SetFieldValue(item, term, 1033);
				}

				// assume success
				isSuccess = true;
			}
			catch (Exception ex)
			{
				string extraInfo = string.Empty; if (terms != null && terms.Count > 0) { foreach (Term t in terms) { extraInfo += t.Name + ", "; } }
				Log.WriteError("rete7Gkfrer67", ex, "Field: " + fieldname + " terms: " + extraInfo);
				isSuccess = false;
			}
			return isSuccess;
		}


		public static bool SetManagedMetadataField(SPListItem item, string fieldname, TaxonomyFieldValueCollection terms, 
			bool isAppendExistingValue)
		{
			bool isSuccess = false;
			try
			{
				// init
				if (item == null) { throw new Exception("SPItem passed is null"); }
				if (string.IsNullOrEmpty(fieldname)) { throw new Exception("Fieldname passed is null"); }
				if (terms == null || terms.Count == 0) { throw new Exception("Invalid terms collection passed"); }

				// get field from item
				SPField field = null; field = GetField(item, fieldname);
				if (field == null) { throw new Exception("Failed to get field for item using fieldname: " + fieldname); }

				// make sure not assigning multiple terms
				if (!((TaxonomyField)field).AllowMultipleValues)
				{
					if (terms.Count > 1)
					{
						throw new Exception("Cannot assign more than one term to managed metadata field that only allows one term");
					}
					else if (isAppendExistingValue)
					{
						throw new Exception("Cannot append a term to a managed metadata field that only allows one term");
					}
				}

				// get SPsite
				SPSite site = item.ParentList.ParentWeb.Site;
				if (site == null) { throw new Exception("Failed to get SPSite for item passed"); }

				// append?
				if (isAppendExistingValue)
				{
					// get existing terms value
					var existingTerms = GetManagedMetadataValue(item, fieldname);
					if (existingTerms != null && existingTerms.Count > 0)
					{
						// append terms
						foreach (var t in existingTerms)
						{
							if (!terms.Contains(t)) { terms.Add(t); }
						}
					}
				}

				// set property
				if (terms.Count > 1)
				{
					((TaxonomyField)field).SetFieldValue(item, terms);
				}
				else if (terms.Count == 1)
				{
					TaxonomyFieldValue term = null;
					foreach (var t in terms) { term = t; break; }
					((TaxonomyField)field).SetFieldValue(item, term);
				}

				// assume success
				isSuccess = true;
			}
			catch (Exception ex)
			{
				string extraInfo = string.Empty; if (terms != null && terms.Count > 0) { foreach (var t in terms) { extraInfo += t.Label + ", "; } }
				Log.WriteError("tr7fjgftydfy", ex, "Field: " + fieldname + " terms: " + extraInfo);
				isSuccess = false;
			}
			return isSuccess;
		}

		/// <summary>
		/// Set Managed Metadata field using single TaxonomyFieldValue 
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <param name="term"></param>
		/// <param name="isAppendExistingValue"></param>
		/// <returns></returns>
		public static bool SetManagedMetadataField(SPListItem item, string fieldname, TaxonomyFieldValue term,
			bool isAppendExistingValue)
		{
			bool isSuccess = false;
			try
			{
				// init
				if (term == null) { throw new Exception("TaxonomyFieldValue passed is null"); }
				if (!Field.IsExist(item, fieldname)) { throw new Exception("Fieldname passed is invalid: " + fieldname); }

				// get taxonomy field reference
				TaxonomyField f = item[fieldname] as TaxonomyField;

				// create taxonomy field collection (just so I can call the original member)
				TaxonomyFieldValueCollection terms = new TaxonomyFieldValueCollection(f);
				if (terms == null) { throw new Exception("Failed to create TaxonomyFieldValueCollection"); }
				terms.Add(term);

				// call original
				isSuccess = Field.SetManagedMetadataField(item, fieldname, terms, isAppendExistingValue);
			}
			catch (Exception ex)
			{
				Log.WriteError("r68gkgcfgdxfdgxgr", ex);
				isSuccess = false;
			}
			return isSuccess;
		}

		/// <summary>
		/// Set term for managed metadata field
		/// overload
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <param name="term"></param>
		/// <param name="isAppendExistingValue"></param>
		/// <returns></returns>
		public static bool SetManagedMetadataField(SPListItem item, string fieldname, Term term, bool isAppendExistingValue)
		{
			List<Term> terms = new List<Term>(); if (term != null) { terms.Add(term); }
			// call original
			return SetManagedMetadataField(item, fieldname, terms, isAppendExistingValue);
		}

		/// <summary>
		/// Assign terms to a managed metadata column
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <param name="termIds">array of Guid termIds </param>
		/// <returns></returns>
		public static bool SetManagedMetadataField(SPListItem item, string fieldname, Guid[] termIds, bool isAppendExistingValue)
		{
			bool isSuccess = false;
			try
			{
				// init
				if (item == null) { throw new Exception("SPItem passed is null"); }
				if (string.IsNullOrEmpty(fieldname)) { throw new Exception("Fieldname passed is null"); }
				if (termIds == null || termIds.Length == 0) { throw new Exception("termIds array passed is null or empty"); }


				// convert guid array into list
				List<Guid> termIdsList = new List<Guid>();
				foreach (Guid g in termIds)
				{
					if (!termIdsList.Contains(g)) { termIdsList.Add(g); }
				}

				// get SPsite
				SPSite site = item.ParentList.ParentWeb.Site;
				if (site == null) { throw new Exception("Failed to get SPSite for item passed"); }

				// get term store
				TermStore store = Taxonomy.GetTermStore(site);
				if (store == null) { throw new Exception("Failed to get termStore"); }

				// get terms
				TermCollection terms = Taxonomy.GetTerms(termIdsList.ToArray(), store);
				if (terms == null) { throw new Exception("Failed to get terms using passed termIds"); }

				// add to list
				List<Term> _terms = new List<Term>();
				foreach (Term t in terms) { if (t != null) { _terms.Add(t); } } 

				isSuccess = SetManagedMetadataField(item, fieldname, _terms, isAppendExistingValue);
			}
			catch (Exception ex)
			{
				Log.WriteError("rete7kfrer67", ex, "Field: " + fieldname);
				isSuccess = false;
			}
			return isSuccess;
		}

		public static bool SetManagedMetadataField(SPListItem item, string fieldname, Guid termId, bool isAppendExistingValue)
		{
			Guid[] termIds = null; if (termId != null) { termIds = new Guid[] { termId }; }
			// call original
			return SetManagedMetadataField(item, fieldname, termIds, isAppendExistingValue);
		}

		/// <summary>
		/// Add terms to managed metadata field
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <param name="termstoAdd"></param>
		/// <returns></returns>
		public static bool AddManagedMetadataTerms(SPListItem item, string fieldname, ICollection<Term> termstoAdd)
		{
			return SetManagedMetadataField(item, fieldname, termstoAdd, true);
		}

		/// Remove terms from managed metadata field
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <param name="termIdsToRemove"></param>
		/// <returns></returns>
		public static bool RemoveManagedMetadataTerms(SPListItem item, string fieldname, List<Guid> termIdsToRemove)
		{
			bool isSuccess = false;
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (string.IsNullOrEmpty(fieldname)) { throw new Exception("No fieldname passed"); }
				if (termIdsToRemove == null) { throw new Exception("TermIds collection passed is null"); }


				// get field
				var field = Field.GetField(item, fieldname);
				if (!(field is TaxonomyField)) { throw new Exception("Fieldname passed: " + fieldname + ", is not a TaxonomyField"); }

				// get existing value(s)
				TaxonomyFieldValueCollection existingTerms = null;
				TaxonomyFieldValue existingTerm = null;
				object fieldValue = null; try { fieldValue = item[fieldname]; }
				catch { }
				if (fieldValue == null) { throw new Exception("Failed to get field value  for fieldname: " + fieldname + ". Is it possible that the SPListItem passed has not yet been saved?"); }

				if (fieldValue is TaxonomyFieldValueCollection) { existingTerms = (TaxonomyFieldValueCollection)fieldValue; }
				else if (fieldValue is TaxonomyFieldValue) { existingTerm = (TaxonomyFieldValue)fieldValue; }
				else { throw new Exception("Unknown field type passed, not TaxonomyFieldValue or TaxonomyFieldValueCollection"); }

				// if TaxonomyFieldValueCollection
				if (existingTerms != null && existingTerms.Count > 0)
				{
					bool isMatch = false;
					TaxonomyFieldValue emptyFieldValue = existingTerms[0];

					// find terms to remove
					foreach (Guid id in termIdsToRemove)
					{
						for (int i = 0; i < existingTerms.Count; i++)
						{
							if (id.ToString() == existingTerms[i].TermGuid)
							{
								existingTerms.RemoveAt(i);
								isMatch = true;
								break;
							}
						}
					}

					// set field value
					if (isMatch)
					{
						if (existingTerms.Count == 0)
						{
							// set to an empty taxonomyfield value
							// http://blog.beckybertram.com/Lists/Posts/Post.aspx?List=5489bebf-bd8d-4a6f-995b-3a0a456796f6&ID=124&Web=316c15c2-6bc0-464f-bda1-7ba96b4ba453
							emptyFieldValue.WssId = 0;
							emptyFieldValue.TermGuid = null;
							emptyFieldValue.Label = null;
							((TaxonomyField)field).SetFieldValue(item, emptyFieldValue);
						}
						else
						{
							// some terms still remain, update
							((TaxonomyField)field).SetFieldValue(item, existingTerms);
						}
					}

				}
				else
				{
					// single field value, set it to empty term
					bool isMatch = false;
					TaxonomyFieldValue emptyFieldValue = null;
					if (existingTerm != null) { emptyFieldValue = existingTerm; }

					// find terms to remove
					foreach (Guid id in termIdsToRemove)
					{
						if (id.ToString() == existingTerm.TermGuid)
						{
							existingTerm = null;
							isMatch = true;
							break;
						}
					}

					// set field value
					if (isMatch)
					{
						if (emptyFieldValue == null) { throw new Exception("Unknown error, empty tax field value is null"); }
						// set to an empty taxonomyfield value
						// http://blog.beckybertram.com/Lists/Posts/Post.aspx?List=5489bebf-bd8d-4a6f-995b-3a0a456796f6&ID=124&Web=316c15c2-6bc0-464f-bda1-7ba96b4ba453
						emptyFieldValue.WssId = 0;
						emptyFieldValue.TermGuid = null;
						emptyFieldValue.Label = null;
						((TaxonomyField)field).SetFieldValue(item, emptyFieldValue);
					}
				}

				// assume success
				isSuccess = true;
			}
			catch (Exception ex)
			{
				string extraInfo = string.Empty; if (termIdsToRemove != null && termIdsToRemove.Count > 0) { foreach (Guid id in termIdsToRemove) { extraInfo += id.ToString() + ", "; } }
				Log.WriteError("7t89GGyuYYftrdHhdrgsgdrrdg", ex, "Field: " + fieldname + " termIds to remove: " + extraInfo);
				isSuccess = false;
			}
			return isSuccess;
		}

		public static bool RemoveManagedMetadataTerms(SPListItem item, string fieldname, ICollection<Term> termsToRemove)
		{
			var termIds = new List<Guid>();
			if (termsToRemove != null && termsToRemove.Count > 0)
			{
				foreach (Term t in termsToRemove)
				{
					termIds.Add(t.Id);
				}
			}
			return RemoveManagedMetadataTerms(item, fieldname, termIds);
		}

		public static bool RemoveManagedMetadataTerms(SPListItem item, string fieldname, ICollection<TaxonomyFieldValue> termsToRemove)
		{
			var termIds = new List<Guid>();
			if (termsToRemove != null && termsToRemove.Count > 0)
			{
				foreach (TaxonomyFieldValue t in termsToRemove)
				{
					termIds.Add(new Guid(t.TermGuid));
				}
			}
			return RemoveManagedMetadataTerms(item, fieldname, termIds);
		}

		///// <summary>
		///// Compare managed metadata field value against collection of terms
		///// if false, different
		///// 
		///// </summary>
		///// <param name="fieldValue"></param>
		///// <param name="terms"></param>
		///// <returns></returns>
		//public static bool CompareManagedMetadataFieldAgainstTermsCollection(List<TaxonomyFieldValue> fieldValue, IEnumerable<Term> terms, 
		//    out List<Term> termsToRemoveFromField, out List<Term> termsToAddToField)
		//{
		//    bool isSame = false;
		//    try
		//    {
		//        if (fieldValue == null) { throw new Exception("field value collection of TaxonomyFieldValues passed is null"); }
		//        if (terms == null) { throw new Exception("
		//    }
		//    catch (Exception ex)
		//    {
		//        Log.WriteError("54y6it8ufyfgdfsdfzst", ex);
		//    }
		//}

		/// <summary>
		/// Get TaxonomyFieldValueCollection (for Managed Metadata field that only allows many values)
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static TaxonomyFieldValueCollection GetManagedMetadataTaxonomyFieldValueCollection(SPListItem item, string fieldname)
		{
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (string.IsNullOrEmpty(fieldname)) { throw new Exception("Fieldname passed is null"); }


				// get field
				object field = null;
				try { field = item[fieldname]; } catch { }
				if (field == null) { throw new Exception("Failed to find field in passed item. Fieldname: " + fieldname + ". Is it possible that the SPListItem passed has not yet been saved?"); }
				
				// TaxonomyFieldValueCollection type?
				if (field is TaxonomyFieldValueCollection) { return (TaxonomyFieldValueCollection)field; }
				else
				{
					string extraErrorInfo = null;
					if (field is TaxonomyFieldValue) { extraErrorInfo = ". Passed field is instead TaxonomyFieldValue type. Call GetManagedMetadataTaxonomyFieldValue() instead"; }
					throw new Exception("Field passed is not of TaxonomyFieldValueCollection type" + extraErrorInfo);
				}
			}
			catch (Exception ex)
			{
				string title = null; if (item != null) { title = item.Title; }
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("reujdfgxfgfdrsgtdrt", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title);
				return null;
			}
		}
		/// <summary>
		/// Get TaxonomyFieldValue (for Managed Metadata field that only allows 1 value)
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static TaxonomyFieldValue GetManagedMetadataTaxonomyFieldValue(SPListItem item, string fieldname)
		{
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (string.IsNullOrEmpty(fieldname)) { throw new Exception("Fieldname passed is null"); }


				// get field
				object field = null;
				try { field = item[fieldname]; } catch { }
				if (field == null) { throw new Exception("Failed to find field in passed item. Fieldname: " + fieldname + ". Is it possible that the SPListItem passed has not yet been saved?"); }

				// TaxonomyFieldValueCollection type?
				if (field is TaxonomyFieldValue) { return (TaxonomyFieldValue)field; }
				else
				{
					string extraErrorInfo = null;
					if (field is TaxonomyFieldValueCollection) { extraErrorInfo = ". Passed field is instead TaxonomyFieldValueCollection type. Call GetManagedMetadataTaxonomyFieldValueCollection() instead"; }
					throw new Exception("Field passed is not of TaxonomyFieldValue type" + extraErrorInfo);
				}
			}
			catch (Exception ex)
			{
				string title = null; if (item != null) { title = item.Title; }
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("rtsucgffxgdfdtr6787rf", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title);
				return null;
			}
		}


		/// <summary>
		/// Get terms from Managed Metadata field
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static List<TaxonomyFieldValue> GetManagedMetadataValue(SPListItem item, string fieldname)
		{
			List<TaxonomyFieldValue> terms = null;
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (string.IsNullOrEmpty(fieldname)) { throw new Exception("Fieldname passed is null"); }
				terms = new List<TaxonomyFieldValue>();


				// get field as generic object (don't know it's type yet)
				object field = null; try { field = item[fieldname]; } catch { }
				if (field == null) { throw new Exception("Failed to find field in passed item. Fieldname: " + fieldname + ". Is it possible that the SPListItem passed has not yet been saved?"); }

				if (field is TaxonomyFieldValueCollection)
				{
					foreach (TaxonomyFieldValue t in (TaxonomyFieldValueCollection)field)
					{
						terms.Add(t);
					}
				}
				else if (field is TaxonomyFieldValue)
				{
					terms.Add((TaxonomyFieldValue)field);
				}
				else
				{
					throw new Exception("Unknown field type for field: " + fieldname + ", not TaxonomyFieldValueCollection or TaxonomyFieldValue type");
				}
			}
			catch (Exception ex)
			{
				string title = null; if (item != null) { title = item.Title; }
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("rthygfdxfGGsdsrdr", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title);
				terms = null;
			}
			return terms;
		}

		//public static List<Term> GetManagedMetadataValue(TermStore termStore, SPListItem item, string fieldname)
		//{
		//    List<Term> terms = null;
		//    try
		//    {
		//        // init
		//        if (termStore == null) { throw new Exception("TermStore passed is null"); }
		//        if (item == null) { throw new Exception("SPListItem passed is null"); }
		//        if (string.IsNullOrEmpty(fieldname)) { throw new Exception("Fieldname passed is null"); }
		//        terms = new List<Term>();

		//        // call original
		//        List<TaxonomyFieldValue> existingTerms = GetManagedMetadataValue(item, fieldname);
		//        if (existingTerms != null && existingTerms.Count > 0)
		//        {
		//            // get term guids
		//            List<Guid> existingTermGuids = new List<Guid>();
		//            foreach (TaxonomyFieldValue t in existingTerms)
		//            {
		//                Guid newTermGuidId = new Guid(t.TermGuid);
		//                if (newTermGuidId != null && newTermGuidId != Guid.Empty && !existingTermGuids.Contains(newTermGuidId))
		//                {
		//                    existingTermGuids.Add(newTermGuidId);
		//                }
		//            }

		//            // now get terms
		//            TermCollection _terms = Taxonomy.GetTerms(termStore, existingTermGuids.ToArray());
		//            foreach (Term t in _terms) { terms.Add(t); }
		//        }
		//    }
		//    catch (Exception ex)
		//    {
		//        string title = null; if (item != null) { title = item.Title; }
		//        string contentType = ContentType.GetContentTypeName(item);
		//        string id = null; if (item != null) { id = item.ID.ToString(); }
		//        Log.WriteError("t7idyrfdxfdee5d", ex, "fieldname: " + fieldname + " content type: " + contentType + " item.id: " + id + " title: " + title);
		//        terms = null;
		//    }
		//    return terms;
		//}


		public static SPFieldMultiChoiceValue GetMultiChoiceValues(SPListItem item, string fieldname)
		{
			SPFieldMultiChoiceValue o = null;
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (!IsExist(item, fieldname)) { throw new Exception("Field: " + fieldname + " does not exist for passed item"); }


				if (item[fieldname] == null) { o = new SPFieldMultiChoiceValue(); }
				else { o = new SPFieldMultiChoiceValue(item[fieldname].ToString()); }
			}
			catch (Exception ex)
			{
				string title = null; if (item != null) { title = item.Title; }
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("esy5fjygdgrdfdtrrytt6t67", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title);
				o = null;
			}
			return o;
		}

		/// <summary>
		/// Get the multichoice values for passed field, returns collection instead of SPFieldMultiChoiceValue
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static List<string> GetMultiChoiceValuesAsList(SPListItem item, string fieldname)
		{
			var o = new List<string>();
			
			// get multichoice value
			var choices = GetMultiChoiceValues(item, fieldname);

			if (choices != null && choices.Count > 0)
			{
				for (int i = 0; i < choices.Count; i++) { o.Add(choices[i]); }
			}
			
			return o;
		}

		public static bool SetMultiChoiceField(SPListItem item, string fieldname, string[] values, bool isAppend)
		{
			bool isSuccess = true;
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (!IsExist(item, fieldname)) { throw new Exception("Field: " + fieldname + " does not exist for passed item"); }


				// get field value
				var currentValues = GetMultiChoiceValues(item, fieldname);
				if (currentValues == null) { currentValues = new SPFieldMultiChoiceValue(); }


				// set values
				var newValues = new SPFieldMultiChoiceValue();
				if (values != null && values.Length > 0)
				{
					foreach (string v in values) { newValues.Add(v); }
				}

				// append?
				if (isAppend && currentValues.Count > 0)
				{
					List<string> valuesToAppend = new List<string>();
					for (int i = 0; i < currentValues.Count; i++)
					{
						bool isMatch = false;
						for (int ii = 0; ii < newValues.Count; ii++)
						{
							if (string.Compare(currentValues[i], newValues[ii], true) == 0)
							{
								isMatch = true;
								break;
							}
						}
						if (!isMatch)
						{
							// current value not in new values, add it
							valuesToAppend.Add(currentValues[i]);
						}
					}
					if (valuesToAppend.Count > 0)
					{
						foreach (string v in valuesToAppend) { newValues.Add(v); }
					}
				}

				// set values
				item[fieldname] = newValues;
			}
			catch (Exception ex)
			{
				string title = null; if (item != null) { title = item.Title; }
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("7689utrgffgdfftfdyse", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title);
				isSuccess = false;
			}
			return isSuccess;
		}




		/// <summary>
		/// Change the default "Title" display name for title field.
		/// IMPORTANT: Saves changes immediately!
		/// </summary>
		/// <param name="list"></param>
		/// <param name="newDisplayName"></param>
		/// <returns></returns>
		public static bool ChangeTitleDisplayName(SPList list, string newDisplayName)
		{
			bool isSuccess = false;
			try
			{
				// init
				if (list == null) { throw new Exception("SPList passed is null"); }
				if (!IsExist(list, "Title")) { throw new Exception("Title field does not exist"); }

				list.ParentWeb.AllowUnsafeUpdates = true;
				SPField title = list.Fields["Title"];
				title.Title = newDisplayName;
				title.Update(true);
				list.Update();
				list.ParentWeb.AllowUnsafeUpdates = false;

				// assume success
				isSuccess = true;
			}
			catch (Exception ex)
			{
				Log.WriteError("zdfxhghgddfdfsdtrdf", ex, "new display name for title field: " + newDisplayName);
				isSuccess = false;
			}
			finally
			{
				if (list != null && list.ParentWeb != null && list.ParentWeb.AllowUnsafeUpdates == true)
				{
					list.ParentWeb.AllowUnsafeUpdates = false;
				}
			}
			return isSuccess;
		}


		/// <summary>
		/// Get LookupField. This provides lookup listId, lookup webId, etc.
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static SPFieldLookup GetLookupField(SPListItem item, string fieldname)
		{
			SPFieldLookup f = null;
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (string.IsNullOrEmpty(fieldname)) { throw new Exception("Fieldname passed is null"); }

				
				// 1.) get field
				SPField _f = item.Fields.GetField(fieldname);
				if (_f == null) { throw new Exception("Failed to get field: " + fieldname); }

				// 2.) cast
				f = (SPFieldLookup)_f;
			}
			catch (Exception ex)
			{
				string title = null; if (item != null) { title = item.Title; }
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("e5yyersdgrsssere", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title);
				f = null;
			}
			return f;
		}

		/// <summary>
		/// Get lookup field values in an itemId, string value format
		/// Note that if the lookup field links to another item's Id,
		/// then the returned values will be itemId int and itemId string pair
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static Dictionary<int, string> GetLookupValues(SPListItem item, string fieldname)
		{
			Dictionary<int, string> lookupValues = null;
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (!IsExist(item, fieldname)) { throw new Exception("Field: " + fieldname + " does not exist for passed item"); }
				lookupValues = new Dictionary<int, string>();
				bool isEmptyField = false;
				SPFieldLookupValue value = null;
				SPFieldLookupValueCollection values = null;

				// 1.) get SPFieldLookup
				SPFieldLookup f = GetLookupField(item, fieldname);
				if (f == null) { throw new Exception("Failed to get SPFieldLookup using fieldname: " + fieldname); }
				if (string.IsNullOrEmpty(f.LookupList)) { throw new Exception("SPFieldLookup does not have a lookup list defined"); }

				// 2.) get values and determine if field empty
				if (f.AllowMultipleValues == false) { value = item[fieldname] as SPFieldLookupValue; }
				else { values = item[fieldname] as SPFieldLookupValueCollection; }
				if (value == null && values == null) { isEmptyField = true; }
				else if (value != null && value.LookupId == 0) { isEmptyField = true; }
				else if (values != null && values.Count == 0) { isEmptyField = true; }

				if (!isEmptyField)
				{
					// 3.) get lookup items
					if (value != null)
					{
						lookupValues.Add(value.LookupId, value.LookupValue);
					}
					else
					{
						for (int i = 0; i < values.Count; i++)
						{
							lookupValues.Add(values[i].LookupId, values[i].LookupValue);
						}
					}
				}
			}
			catch (Exception ex)
			{
				string title = null; if (item != null) { title = item.Title; }
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("r6styusrtdrssresre", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title);
				lookupValues = null;
			}
			return lookupValues;
		}


		/// <summary>
		/// Get lookup list items based on lookup field
		/// For example, if standard linked to 5 mfgs, 
		/// then pass that lookup field and will return the 5 SPListItem mfgs
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <param name="lookupList">Can be null, only pass if already know. Otherwise will find</param>
		/// <returns></returns>
		public static List<SPListItem> GetLookupItems(SPListItem item, string fieldname, SPList lookupList)
		{
			List<SPListItem> items = null;
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (!IsExist(item, fieldname)) { throw new Exception("Field: " + fieldname + " does not exist for passed item"); }
				items = new List<SPListItem>();


				// 1.) call original and get lookup values in raw format
				Dictionary<int, string> lookupValues = GetLookupValues(item, fieldname);
				if (lookupValues == null) { throw new Exception("Failed to get lookup values"); }

				if (lookupValues.Count > 0)
				{
					// 2.) get lookup field
					SPFieldLookup f = GetLookupField(item, fieldname);
					if (f == null) { throw new Exception("Failed to get SPFieldLookup using fieldname: " + fieldname); }

					// 3.) get lookup list's web
					SPWeb web = Web.GetWeb();
					if (web == null || web.ID != f.LookupWebId)
					{
						// need to manually lookup the SPWeb
						web = Web.GetWeb(f.LookupWebId, item.Web.Site);
						if (web == null) { throw new Exception("Failed to get lookup list's web using lookupWebId: " + f.LookupWebId); }
					}

					// 4.) get lookup list
					if (lookupList == null)
					{
						lookupList = List.GetListById(web, new Guid(f.LookupList));
						if (lookupList == null) { throw new Exception("Failed to get lookup list using id: " + f.LookupList); }
					}

					// 5.) foreeach lookup value, get correspeonding list item
					List<int> itemIds = new List<int>();
					foreach (KeyValuePair<int, string> v in lookupValues) { itemIds.Add(v.Key); }
					SPListItemCollection _items = Item.GetItems(lookupList, itemIds.ToArray());
					if (_items == null) { throw new Exception("Failed to fetch list items using itemIds: " + Utilities.ConvertArrayToString(itemIds.ToArray())); }
					if (_items.Count != lookupValues.Count) 
					{ 
						// determine which items failed to get
						Log.WriteError("sstrdudytdsdzsr5cfxxdf", "Failed to fetch all list items using itemsId array: " + Utilities.ConvertArrayToString(itemIds.ToArray())); 
					}
					items = Item.ConvertSPListItemCollectionToGenericCollection(_items);
				}
			}
			catch (Exception ex)
			{
				string title = null; if (item != null) { title = item.Title; }
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("r6styusrtdrssresre", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title);
				items = null;
			}
			return items;
		}




		/// <summary>
		/// Set lookup field with values
		/// DOES NOT SAVE!
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <param name="lookupValues"></param>
		/// <param name="isAppend"></param>
		/// <returns></returns>
		public static bool SetLookupField(SPListItem item, string fieldname, Dictionary<int, string> lookupValues, bool isAppend)
		{
			bool isSuccess = false;
			try
			{
				// init
				if (item == null) { throw new Exception("SPItem passed is null"); }
				if (string.IsNullOrEmpty(fieldname)) { throw new Exception("Fieldname passed is null"); }
				if (lookupValues == null) { throw new Exception("lookup values dictionary passed is null"); }

				if (lookupValues.Count > 0)
				{
					// 1.) get field
					SPFieldLookup f = GetLookupField(item, fieldname);
					if (f == null) { throw new Exception("Failed to get lookup field with fieldname: " + fieldname); }

					// 2.) make sure not trying to add too many values
					if (!f.AllowMultipleValues)
					{
						if (lookupValues.Count > 1) { throw new Exception("Only allowed to set one value for lookup field: " + fieldname); }
						if (isAppend) { throw new Exception("Cannot append a value to lookup field which only allows one value. Field: " + fieldname); }
					}

					// 3.) get current values if appending
					if (isAppend)
					{
						Dictionary<int, string> currentLookupValues = GetLookupValues(item, fieldname);
						if (currentLookupValues != null && currentLookupValues.Count > 0)
						{
							// now create combined lookup list to update, removing dups
							foreach (KeyValuePair<int, string> currentValue in currentLookupValues)
							{
								bool isMatch = false;
								foreach (KeyValuePair<int, string> newValue in lookupValues)
								{
									if (newValue.Key == currentValue.Key)
									{
										isMatch = true;
										break;
									}
								}
								if (!isMatch)
								{
									lookupValues.Add(currentValue.Key, currentValue.Value);
								}
							}
						}
					}

					// 4.) now set field
					if (!f.AllowMultipleValues)
					{
						foreach (KeyValuePair<int, string> newValue in lookupValues)
						{
							// set only once
							SPFieldLookupValue v = new SPFieldLookupValue(newValue.Key, newValue.Value);
							item[fieldname] = v.ToString();
							break;
						}
					}
					else
					{
						SPFieldLookupValueCollection values = new SPFieldLookupValueCollection();
						foreach (KeyValuePair<int, string> newValue in lookupValues)
						{
							values.Add(new SPFieldLookupValue(newValue.Key, newValue.Value));
						}
						item[fieldname] = values.ToString();
					}
				}
			
				// assume success
				isSuccess = true;
			}
			catch (Exception ex)
			{
				string title = (item != null) ? item.Title : null;
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("fxdhtgfftdGstvcs", ex, "fieldname: " + fieldname + ", content type: " + contentType + ", title: " + title);
				isSuccess = false;
			}
			return isSuccess;
		}

		/// <summary>
		/// Get URL values, returns SPFieldUrlValue object
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static SPFieldUrlValue GetUrlValue(SPListItem item, string fieldname)
		{
			SPFieldUrlValue url = null;
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (!IsExist(item, fieldname)) { throw new Exception("Field: " + fieldname + " does not exist for passed item"); }

				// get url field
				if (item[fieldname] != null) { url = new SPFieldUrlValue(item[fieldname] as string); }
			}
			catch (Exception ex)
			{
				string title = null; if (item != null) { title = item.Title; }
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("dtryhfdddrdrt", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title);
				url = null;
			}
			return url;
		}

		/// <summary>
		/// get only the string url from field, not the url/displayname SharePoint object
		/// </summary>
		/// <param name="item"></param>
		/// <param name="fieldname"></param>
		/// <returns></returns>
		public static string GetUrlOnlyValue(SPListItem item, string fieldname)
		{
			string url = null;
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (!IsExist(item, fieldname)) { throw new Exception("Field: " + fieldname + " does not exist for passed item"); }

				// get url field
				if (item[fieldname] != null) 
				{ 
					var urlObject = new SPFieldUrlValue(item[fieldname] as string);
					if (urlObject != null) { url = urlObject.Url; }
				}
			}
			catch (Exception ex)
			{
				string title = null; if (item != null) { title = item.Title; }
				string contentType = ContentType.GetContentTypeName(item);
				Log.WriteError("fthyjcgfhtxdffdffD", ex, "fieldname: " + fieldname + " content type: " + contentType + " title: " + title);
				url = null;
			}
			return url;
		}

		/// <summary>
		/// Sets the value of an URL-Field.
		/// </summary>
		public static void SetUrlField(SPListItem item, string fieldname, string url, string description)
		{
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (!IsExist(item, fieldname)) { throw new Exception("Field: " + fieldname + " does not exist for passed item"); }

				item[fieldname] = new SPFieldUrlValue()
				{
					Description = description,
					Url = url
				};
			}
			catch (Exception ex)
			{
				Log.WriteError("dfgghjjgtydrxhgxc", ex, "fieldname: " + fieldname);
			}
		}


		///// <summary>
		///// Update a list item's field for tags
		///// http://stackoverflow.com/questions/2745769/programmatically-set-a-taxonomyfield-on-a-list-item
		///// </summary>
		///// <param name="item"></param>
		///// <param name="fieldname"></param>
		///// <param name="terms"></param>
		///// <returns></returns>
		//public static bool SetManagedMetadataField(SPListItem item, string fieldname, List<Term> terms)
		//{
		//    bool isSuccessful = false;
		//    try
		//    {
		//        // init
		//        if (item == null) { throw new Exception("SPListItem passed is null"); }
		//        if (!Field.IsExist(item, fieldname, false)) { throw new Exception("Tagging field: " + fieldname + " does not exist"); }
		//        if (terms == null || terms.Count == 0) { throw new Exception("Null or empty terms collection passed"); }

		//        // make sure multiple tags allowed if adding more than one tag
		//        if (terms.Count > 1 && !((TaxonomyField)item.Fields[fieldname]).AllowMultipleValues)
		//        { throw new Exception("Cannot add multiple tags when field restricted from allowing multiple values"); }

		//        // loop through terms
		//        foreach (Term term in terms)
		//        {
		//            // a.) create term string
		//            string termString = String.Concat(term.GetDefaultLabel(System.Globalization.CultureInfo.CurrentCulture.LCID),
		//                TaxonomyField.TaxonomyGuidLabelDelimiter, term.Id);

		//            // b.) update field
		//            if (((TaxonomyField)item.Fields[fieldname]).AllowMultipleValues)
		//            {
		//                TaxonomyFieldValueCollection tagValues = new TaxonomyFieldValueCollection((TaxonomyField)item.Fields[fieldname]);
		//                tagValues.PopulateFromLabelGuidPairs(String.Join(TaxonomyField.TaxonomyMultipleTermDelimiter.ToString(),
		//                    new[] { termString })
		//                    );
		//                item[fieldname] = tagValues;
		//            }
		//            else
		//            {
		//                TaxonomyFieldValue tagValue = new TaxonomyFieldValue(termString);
		//                item[fieldname] = tagValue;
		//            }
		//        }

		//        // update
		//        if (isSave) { item.Update(); }

		//        // assume success
		//        isSuccessful = true;
		//    }
		//    catch (Exception ex)
		//    {
		//        Log.WriteError("set5yudt7idrutdtrde", ex);
		//        isSuccessful = false;
		//    }
		//    return isSuccessful;
		//}
			
	}
}
